<template>
  <div class="container">
    <h1>JSON 格式化工具</h1>
    <div class="formatter-area">
      <el-form :model="formData" label-width="120px">
        <el-form-item label="输入 JSON">
          <el-input 
            v-model="formData.input" 
            type="textarea" 
            :rows="10" 
            placeholder="请输入要格式化的 JSON 字符串"
            @input="formatJson"
          />
        </el-form-item>
        <el-form-item label="格式化选项">
          <el-checkbox v-model="formData.pretty">美化输出</el-checkbox>
          <el-checkbox v-model="formData.sortKeys">按键排序</el-checkbox>
          <el-checkbox v-model="formData.removeComments">移除注释</el-checkbox>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="formatJson">格式化</el-button>
          <el-button @click="clearAll">清空</el-button>
          <el-button type="success" @click="copyOutput">复制结果</el-button>
        </el-form-item>
      </el-form>
    </div>

    <div v-if="formData.output" class="output-area">
      <h3>格式化结果</h3>
      <div class="output-container">
        <pre><code>{{ formData.output }}</code></pre>
      </div>
    </div>

    <div v-if="formData.error" class="error-area">
      <el-alert
        :title="formData.error"
        type="error"
        :closable="false"
        show-icon
      />
    </div>
  </div>
</template>

<script setup>
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'

const formData = reactive({
  input: '',
  output: '',
  error: '',
  pretty: true,
  sortKeys: false,
  removeComments: false
})

/**
 * 格式化 JSON
 */
const formatJson = () => {
  if (!formData.input.trim()) {
    formData.output = ''
    formData.error = ''
    return
  }

  try {
    // 移除注释（如果启用）
    let jsonStr = formData.input
    if (formData.removeComments) {
      jsonStr = jsonStr.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '')
    }

    // 解析 JSON
    let parsedJson = JSON.parse(jsonStr)

    // 按键排序（如果启用）
    if (formData.sortKeys) {
      parsedJson = sortObjectKeys(parsedJson)
    }

    // 格式化输出
    if (formData.pretty) {
      formData.output = JSON.stringify(parsedJson, null, 2)
    } else {
      formData.output = JSON.stringify(parsedJson)
    }

    formData.error = ''
  } catch (error) {
    formData.error = `JSON 解析错误: ${error.message}`
    formData.output = ''
  }
}

/**
 * 递归排序对象的所有键
 * @param {Object} obj - 要排序的对象
 * @returns {Object} - 排序后的对象
 */
const sortObjectKeys = (obj) => {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }

  if (Array.isArray(obj)) {
    return obj.map(item => sortObjectKeys(item))
  }

  const sortedObj = {}
  Object.keys(obj).sort().forEach(key => {
    sortedObj[key] = sortObjectKeys(obj[key])
  })

  return sortedObj
}

/**
 * 清空所有输入和输出
 */
const clearAll = () => {
  formData.input = ''
  formData.output = ''
  formData.error = ''
}

/**
 * 复制输出结果到剪贴板
 */
const copyOutput = () => {
  if (!formData.output) return

  navigator.clipboard.writeText(formData.output)
    .then(() => {
      ElMessage.success('已复制到剪贴板')
    })
    .catch(err => {
      console.error('复制失败:', err)
      ElMessage.error('复制失败，请手动复制')
    })
}
</script>

<style scoped>
.container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

h1 {
  text-align: center;
  margin-bottom: 30px;
  color: #303133;
}

.formatter-area {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  margin-bottom: 20px;
}

.output-area {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  margin-bottom: 20px;
}

.output-container {
  background-color: #f5f7fa;
  border-radius: 4px;
  padding: 15px;
  max-height: 400px;
  overflow: auto;
}

.output-container pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-family: 'Courier New', Courier, monospace;
  font-size: 14px;
  line-height: 1.5;
}

.error-area {
  margin-top: 20px;
}

.el-button {
  margin-right: 10px;
}
</style> 